/**
 * 迭代器解决了什么问题: ES6之前遍历方式写法各异,没有一个统一标准,迭代器提供了一个统一的遍历接口
 * 
 * 迭代器: 统一接口 + 惰性消费 + 可中途终止
 *      底层只有两条协议:
 *          1.对象带Symbol.iterator方法
 *          2.Symbol.iterator返回的对象带next(),每次出{value,done}
 * 
 */


let obj={
    a : 1,
    b : 2,
    c : 3
}

// console.log(obj[Symbol.iterator]) //只有存在Symbol.iterator属性的对象才叫可迭代对象

//给对象部署迭代器
obj[Symbol.iterator] = function* () { //function* 叫做生成器函数,调用后不会跑代码,而是返回一个迭代器对象
    for (let i = 0; i < Object.keys(this).length; i++) {
         //迭代器对象自带 next()，每次 next() 会跑到下一个 yield 停住,并返回{value,done},value是yield后面的值,done是是否遍历完
        yield [Object.keys(this)[i],this[Object.keys(this)[i]]];
    }
   
}


// obj[Symbol.iterator]()是一个迭代器对象,因为obj[Symbol.iterator]是一个生成器函数,迭代器对象会有一个next方法
//每次调用这个next方法,就会跑到下一个yield中停下来等待继续调用next方法,如果没有yield,则next方法会返回{value:undefined,done:true}
const it = obj[Symbol.iterator]()
console.log(it.next())
console.log(it.next())
console.log(it.next()) //最后一个元素的done还是会返回false,无法提前预判是否遍历完了
console.log(it.next()) //{value:undefined,done:true},done为true表示迭代器已经遍历完了


//for of 会自动调用迭代器对象的next方法,并且拿到next方法返回的value,直到done为true为止
for (const x of obj) console.log(x); // 1 2 3





